package com.scheduler.actor;

import lombok.*;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.Map;
import java.util.StringJoiner;

/**
 * Actor 消息
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ActorMessage {

    /**
     * @see TaskType
     */
    private String taskType;
    /**
     * 消息带的对象，也就是参数。不需要反序列化，业务自己反序列化。
     */
    private String object;
    /**
     * 对象类，如有必要，业务可以自己写入该类型，用于处理时识别，如JSON反序列化
     */
    private String objectClass;
    /**
     * 对象分组，第一级，用于分发
     *
     * @see WorkerActor#getName()
     */
    private String actorName;
    /**
     * 对象分组，第二级，用于分发。两级分组方便扩展
     *
     * @see WorkerActor#getDispatcherMap()
     */
    private String actorDispatcher;
    /**
     * 来源IP地址
     */
    private String sourceIp;
    /**
     * 目标IP地址
     */
    private String targetIp;
    /**
     * 简单密码认证，建议用签名替代，仅可在测试过程中使用明文
     */
    private String auth;
    /**
     * 毫秒时间戳
     */
    private long timestamp;
    /**
     * 签名类型，MD5、SHA1、SHA256
     */
    private String signType;
    /**
     * 签名，用于替换明文 auth 传递
     */
    private String sign;
    /**
     * 上下午信息，比如全链路跟踪信息
     */
    private Map<String, Object> contextInfo;

    public enum TaskType {
        /**
         * 普通 RPC 调用，返回值为原始返回值
         */
        SIMPLE,
        /**
         * 多机有回调，会报告任务执行状态（暂未支持）
         */
        MAP_REDUCE,
        /**
         * 多机无回调，返回结果为分发任务成功或失败，固定为 OK 或者 FAIL
         */
        MAP_SIMPLE
    }

    /**
     * 签名并清除auth，默认 sha1
     */
    public void doSignAndClearAuth() {
        StringJoiner stringJoiner = new StringJoiner(":");
        stringJoiner.add(actorName);
        stringJoiner.add(actorDispatcher);
        stringJoiner.add(taskType);
        stringJoiner.add(object);
        stringJoiner.add(String.valueOf(timestamp));
        stringJoiner.add(auth);
        if (signType == null) {
            signType = "sha1";
        }
        if ("sha1".equalsIgnoreCase(signType)) {
            sign = DigestUtils.sha1Hex(stringJoiner.toString());
        }
        if ("sha256".equalsIgnoreCase(signType)) {
            sign = DigestUtils.sha256Hex(stringJoiner.toString());
        }
        if ("md5".equalsIgnoreCase(signType)) {
            sign = DigestUtils.md5Hex(stringJoiner.toString());
        }
        if (sign == null) {
            // 默认 sha1，兜底传参错误的情况
            signType = "sha1";
            sign = DigestUtils.sha1Hex(stringJoiner.toString());
        }
        // 清空auth
        auth = null;
    }
}
